#include <time.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <getopt.h>
#include <stdlib.h>
#include <unistd.h>
#include <libgen.h>
#include <signal.h>
#include <syslog.h>
#include <sqlite3.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include "temperature.h"
#include "logger.h"
#include "sqlite3.h"
#include "socket.h"

#define LEN		128

typedef struct 	sample_data_s
{
	char	ID[16];
	char	datatime[32];
	float	temp;

}sample_data_t;

void 	print_usage(char *progname);
void 	signal_handler(int signum);
void	get_sys_time(char *datatime);
int 	get_sample_data(sample_data_t *s_data, char *sample); 

int	g_stop = 0;

int main(int argc, char **argv)
{
	int			ch;
	int 			rv = -1;
	int			port = 0;
	int			daemon_run = 0;
	int			nrow = 0;
	int			len = 128;
	int			clifd = -1;
	int			ret = -1;
	int			time_limit = 0;
	int			sample_flag;
	char			sample[64];
	char			data[64];
	char			*db_name = "temperature.db";
	char			*servip = NULL;
	time_t			now_time = 0;
	time_t			last_time = 0;
	sqlite3			*db = NULL;
	sample_data_t		s_data;
	struct	sockaddr_in	servaddr;

	struct  option      opts[] = {
        {"ipaddr", required_argument, NULL, 'i'},
        {"port", required_argument, NULL, 'p'},
	{"time_limit", required_argument, NULL, 't'},
	{"daemon", no_argument, NULL, 'd'},
        {"help", no_argument, NULL, 'h'},
        {NULL, 0, NULL, 0}
	};

	char	*progname = basename(argv[0]);

    	while((ch = getopt_long(argc, argv, "i:p:t:dh", opts, NULL)) != -1)
    	{
        	switch(ch)
        	{
           		case 'i':
            	    		servip = optarg;
               	    		break;
           		case 'p':
                		port = atoi(optarg);
                    		break;
	   		case 't':
				time_limit = atoi(optarg);
	       	    		break;
	     		case 'd':
				daemon_run = 1;
		    		break;
            		case 'h':
                		print_usage(argv[0]);
               	    		return 0;
        	}
    	}

   	if(!servip || !port || !time_limit)
   	{
        	print_usage(progname);
       		return 0;
   	}

	//后台运行
	if(daemon_run)
	{
		daemon(1, 0);
	}
		
	//捕捉信号
	signal(SIGTERM, signal_handler);
	signal(SIGPIPE, signal_handler);

	//日志
	if(logger_init("log.txt", LOG_LEVEL_DEBUG) < 0)
	{
		fprintf(stderr, "initail logger system failure\n");
		return 2;
	}

	//打开或创建数据库、建表
	rv = database_init(&db, db_name);
	if(rv < 0)
	{
		log_error("database_init() failure: %s\n", strerror(errno));
		return -1;
	}

	//连接服务器
	clifd = connect_server(port, servip);
	
	while(!g_stop)
	{
		//设置采样标志
		sample_flag = 0;
		now_time = time(NULL);
		if(now_time - last_time >= time_limit)
		{
			//获取上报的字符串
			rv = get_sample_data(&s_data, sample);
			if(rv < 0)
			{
				log_error("Get the sample data failure: %s\n", strerror(errno));
				continue;
			}
			last_time = now_time;
			sample_flag = 1;
		}

			//先判断是否连接上服务器（用clifd的值，作为判断是否连接上服务器的标志）
			//此时为：未连接上服务器
			if(clifd < 0)
			{
				log_error("Client connect with server failure: %s\n", strerror(errno));

				//没连上服务器的调用该函数进行连接
				clifd = connect_server(port, servip);

				//没连上的打印信息、记录日志
				if(clifd < 0)
				{
					log_debug("\nStart waiting connect with server again...\n");

					//当客户端与服务器端断开连接时，将此时要发送的数据保存到数据库中
					if(sample_flag)
					{
						if(database_insert(db, sample) < 0)
						{
							log_error("Save data to database failure: %s\n", strerror(errno));
						}
						else
						{
							log_info("Data is sended to database and saved!\n");
						}
					}
				}
			}

			//客户端连上服务器端后，开始发送数据
			else if(clifd >=0)
			{
				log_debug("Socket() create clifd[%d] and connect with server OK!\n", clifd);

				//发送实时数据和数据库中的数据
				//实时数据发送失败、将数据存到数据库中
				if(sample_flag)
				{
					if(write(clifd, sample, sizeof(sample)) < 0)
					{


						log_error("Send data from sample failure:%s\n", strerror(errno));
						ret = database_insert(db, sample);
						if(ret < 0)
						{
							log_error("Save data to database failure: %s\n", strerror(errno));
						}
						else
						{
							log_info("Save data to database OK!\n");
						}
						close(clifd);
						clifd = -1;
					}
					else
					{
						log_info("Send sample to server OK!\n");
					}
				}

				//若成功取出数据库中的第一条数据，证明数据库不为空
				if( 0 == database_pop_first(db, data))
				{
					//发送从数据库中取出的数据
					rv = write(clifd, data, sizeof(data));
					if(rv < 0)
					{
						log_warn("Send data from database failure: %s\n", strerror(errno));
						close(clifd);
						clifd = -1;
					}
					else
					{
						log_debug("Send data from database OK!\n");

						//发送一条数据成功就删除一条数据
						rv = database_delete_first(db);
						if(rv < 0)
						{
							log_warn("Delete data from database failure: %s\n", strerror(errno));
						}
						else
						{
							log_info("Delete data from database OK!\n");
						}
					}
				
				}

				//数据库为空
				else
				{
					log_debug("The database is NULL!\n");
				}
			}
	}
	logger_term();
	database_term(db);
}

//获取采样的数据
int get_sample_data(sample_data_t *s_data, char *sample) 
{
	int		rv = -1;

	rv = get_temperature(&(s_data->temp));	
	if(rv < 0)
	{
		log_error("Get the ds18b20 temperature failure: %s\n", strerror(errno));
		return -1;
	}

	strncpy(s_data->ID, "xiezongyi001", sizeof(s_data->ID));
	get_sys_time(s_data->datatime);

	memset(sample, 0, sizeof(sample));
	snprintf(sample, LEN, "%s/%s/%.1f°C", s_data->ID, s_data->datatime, s_data->temp);
	
	return 0;
}


//获取系统时间
void get_sys_time(char *datatime)
{
	time_t 		tmp;
	struct tm 	*timp;

	time(&tmp);
	timp = localtime(&tmp);

	memset(datatime, 0, sizeof(datatime));
	strftime(datatime, 128, "%Y-%m-%d %H:%M:%S", timp);
	
	return;
}


void print_usage(char *progname)
{
	log_error("%s usage:\n", progname);
    	log_error("-i(--ipaddr):sepcify server IP address\n");
    	log_error("-p(--port):sepcify server port\n");
    	log_error("-s(--second):sepcify second time\n");
    	log_error("-h(--help):print this heip information\n");

    	return;
}

//安装信号：捕捉SIGTERM信号使程序完整退出，忽略SIGPIPE信号
void signal_handler(int signum)
{
	if( SIGTERM == signum)
	{
		log_error("SIGTERM signal detected\n");
		g_stop = 1;
	}
	else if( SIGPIPE == signum)
	{
		log_warn("SIGPIPE signal detected\n");
	}
}

